#ifndef __TIMER_H__
#define __TIMER_H__

#include <memory.h>
#include <set>
#include <vector>
#include <functional>

#include "thread.h"

namespace johnsonli
{
    class TimerManager;
    //定时器类
    class Timer : public std::enable_shared_from_this<Timer> 
    {
        friend TimerManager;
    public:
        typedef std::shared_ptr<Timer> ptr;

        /**
         * @brief 取消定时器
         */
        bool cancel();

        /**
         * @brief 刷新设置定时器的执行时间
         */
        bool refresh();

        /**
         * @brief 重置定时器时间
         * @param[in] ms 定时器执行间隔时间(毫秒)
         * @param[in] from_now 是否从当前时间开始计算
         */
        bool reset(uint64_t ms, bool from_now);

    private:
        Timer(uint64_t ms, std::function<void()> cb, bool recurring, TimerManager* manager);
        Timer(uint64_t next);
        
    private:
        //比较器，给set用，按时间从小到大排序
        struct Comperator
        {
            bool operator()(const Timer::ptr& lhs, const Timer::ptr& rhs) const;
        };
    

    private:
        bool m_recurring = false;           //是否循环定时器
        uint64_t m_ms = 0;                  //执行周期，等待的时间，ms后执行
        uint64_t m_next = 0;                //下一次要执行的时间，当前时间 + m_ms周期

        std::function<void()> m_cb;         //回调函数
        TimerManager* m_manager = nullptr;  //当前timer在哪个timer管理对象内

    };

    //定时器管理类
    class TimerManager
    {
        friend Timer;
    public:
        typedef RWMutex RWMutexType;

        TimerManager();
        virtual ~TimerManager();

        Timer::ptr addTimer(uint64_t ms, std::function<void()> cb
                            ,bool recurring = false);

        //weak_cond：满足条件再执行，智能指针=0时，就不触发
        Timer::ptr addConditionTimer(uint64_t ms, std::function<void()> cb
                            ,std::weak_ptr<void> weak_cond
                            ,bool recurring = false);


        //获取最近一次定时器执行，还需要等待的时间
        uint64_t getNextTimer();

        //将那些应该执行，但没有执行的定时器删除，并将其回调方法添加到cbs
        void listExpiredCb(std::vector<std::function<void()>>& cbs);

    protected:
        /**
         * @brief 当有新的定时器插入到定时器的首部,执行该函数
         */
        virtual void onTimerInsertedAtFront() = 0;

         /**
         * @brief 将定时器添加到管理器中，如果加在第一个，就会触发onTimerInsertedAtFront
         */
        void addTimer(Timer::ptr val, RWMutexType::WriteLock& lock);

    private:
        /**
         * @brief 检测服务器时间是否被调前了
         */
        bool detectClockRollover(uint64_t now_ms);

    private:
        RWMutexType m_mutex;
        std::set<Timer::ptr, Timer::Comperator> m_timers;
        bool m_tickled = false; // 是否触发了onTimerInsertedAtFront
        uint64_t m_previouseTime = 0;
    };
}

#endif